import pickle

import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import os as os
from sklearn.preprocessing import MinMaxScaler


# 中值平均值滤波
def MedianAvg_Filter(window_left, window_right, arr):
  size = len(arr)
  result = []
  for i in range(window_left, size-window_right):
    # 滑窗
    temp = []
    for j in range(-window_left, window_right+1):
      temp.append(arr[i+j])
    temp.sort()
    # 可以去掉最大值后，取中位数的平均值
    median_mean = []
    for m in range(1, len(temp)-1):
      median_mean.append(temp[m])

    result.append(np.mean(median_mean))
  return result

def input_data(seq,ws):
    out = []
    L = len(seq)
    for i in range(L-ws):
        window = seq[i:i+ws]
        label = seq[i+ws:i+ws+1]
        out.append((window, label))
    return out

def cnn_pre(train_norm, window_size, model):
    future = 100
    # 选取序列最后12个值开始预测
    preds = train_norm[-window_size:].tolist()
    # 设置成eval模式
    model.eval()
    # 循环的每一步表示向时间序列向后滑动一格
    for i in range(future):
        seq = torch.FloatTensor(preds[-window_size:])
        with torch.no_grad():
            preds.append(model(seq.reshape(1,1,-1)).item())
    return preds

class CNNnetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1d = nn.Conv1d(1,64,kernel_size=2)
        self.relu = nn.ReLU(inplace=True)
        self.Linear1= nn.Linear(64*11,50)
        self.Linear2= nn.Linear(50,1)
    def forward(self,x):
        x = self.conv1d(x)
        x = self.relu(x)
        x = x.view(-1)
        x = self.Linear1(x)
        x = self.relu(x)
        x = self.Linear2(x)
        return x

'''
对外调用接口;
提供给外部其他Python文件调用接口.
'''

def data_process(data,url):
    if url:
        df = pd.read_excel(url)
    else:
        df = data
    df.columns = ['y']
    # 滤波后的数据
    data1 = df[:1000]
    data_filter = np.array(MedianAvg_Filter(10, 10, data1['y'])).reshape(-1, 1)

    # 用前1000轮预测后100轮
    train = pd.DataFrame(data_filter)
    test = df[-100:]

    scaler = MinMaxScaler(feature_range=(-1, 1))
    train_norm = scaler.fit_transform(train)

    # 转换成 tensor
    train_norm = torch.FloatTensor(train_norm).view(-1)
    window_size = 12
    train_data = input_data(train_norm, window_size)
    # 当前程序路径问题，进行识别当前路径转换
    print(os.getcwd())
    print("------D_CNN----------")
    curr_url = os.path.join(os.getcwd(), 'CNN_model.pkl')
    # load the saved model
    print(curr_url)
    with open(curr_url, 'rb') as f:
        model = pickle.load(f)

    preds = cnn_pre(train_norm, window_size, model)
    true_predictions = scaler.inverse_transform(np.array(preds[window_size:]).reshape(-1, 1)).tolist()

    # 输出预测值
    return true_predictions

if __name__ =="__main__":
    # 读取文件
    url = 'D_CNN_data.xlsx'
    data = pd.read_excel('D_CNN_data.xlsx')
    true_predictions = data_process(data,url)


    # 输出预测值
    print('Predict:', true_predictions)
